#!/bin/sh
# This regression test is a part of SIPp.
# pcap plays start on multiples of 20 ms: the first packets of the plays
# of a playback thread's calls, which start at other moments, arrive a
# multiple of 20 ms apart.
. "`dirname "$0"`/../functions"

# Sending pcap plays needs a raw socket: run as root in a user and
# network namespace of our own.
if test -z "$SIPP_NETNS"; then
    if unshare -rn true 2>/dev/null; then
        SIPP_NETNS=1 exec unshare -rn "$0"
    fi
    init
    skip "no user network namespaces"
fi
init
"`get_sipp`" -v | grep -q PCAP || skip "no PCAP"
ip link set lo up 2>/dev/null || skip "cannot bring up lo"

calls=20
sippbg -sf uas.xml -i 127.0.0.1 -p 25790 -m $calls -timeout 10
# The streams (port and source port), and how far the first packet of
# the one furthest off is from a multiple of 20 ms after the first
# packet of the first stream, in ms.
rm -f rtp.out
perl -e '
    use Socket; use Time::HiRes qw(time);
    for $p (26750, 26752) {
        socket($s{$p}, PF_INET, SOCK_DGRAM, 17) || die($!);
        setsockopt($s{$p}, SOL_SOCKET, SO_RCVBUF, 1 << 20);
        bind($s{$p}, pack_sockaddr_in($p, inet_aton("127.0.0.1"))) || die($!);
    }
    $end = time + 5;
    while (($now = time) < $end) {
        $r = ""; vec($r, fileno($s{$_}), 1) = 1 for keys %s;
        select($r, undef, undef, $end - $now) > 0 || next;
        for $p (keys %s) {
            vec($r, fileno($s{$p}), 1) || next;
            while ($from = recv($s{$p}, $o, 2048, MSG_DONTWAIT)) {
                ($sp) = unpack_sockaddr_in($from);
                $first{"$p $sp"} //= time;
            }
        }
    }
    @t = sort { $a <=> $b } values %first;
    $off = 0;
    for (@t) {
        $ms = 1000 * ($_ - $t[0]);
        $d = $ms - 20 * int($ms / 20 + 0.5);
        $off = abs($d) if abs($d) > $off;
    }
    printf("%d %.1f\n", scalar(@t), $off);' >rtp.out &
rtp=$!
# 7 calls a second: they start about 143 ms apart, at other phases.
"`get_sipp`" -nostdin -sf uac.xml -i 127.0.0.1 -p 25791 -mp 26000 \
    -m $calls -l $calls -r 7 127.0.0.1:25790 \
    -timeout 10 -timeout_error >/dev/null 2>&1
status=$?
wait $rtp
read streams off <rtp.out
rm -f rtp.out

if test $status -ne 0; then
    fail "UAC failed with $status"
elif test "${streams:-0}" -ne $((2 * calls)); then
    fail "${streams:-0} streams of $calls calls"
elif ! awk "BEGIN { exit !($off < 3) }"; then
    fail "a play starts ${off} ms off the multiples of 20 ms"
else
    ok
fi
